Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | import { useQuery } from '@apollo/client/react';
import { useSession } from 'next-auth/react';
import { useCallback, useMemo, useState } from 'react';
import { GET_RECIPE_BY_ID } from '@/lib/graphql/queries';
import type { RecipeDetailData } from '../types';
import { extractYoutubeId, sortByOrder } from '../utils';
const SERVING_MIN = 1;
const SERVING_MAX = 20;
export const useRecipeDetail = (recipeId: string) => {
const { data: session } = useSession();
const { data, loading, error } = useQuery<RecipeDetailData>(
GET_RECIPE_BY_ID,
{ variables: { id: recipeId } },
);
const recipe = data?.getRecipeById;
/* ── Serving adjuster ── */
const [servingMultiplier, setServingMultiplier] = useState(1);
const adjustedServings = useMemo(
() => (recipe ? recipe.servings * servingMultiplier : 0),
[recipe, servingMultiplier],
);
const incrementServings = useCallback(
() => setServingMultiplier((m) => Math.min(m + 1, SERVING_MAX)),
[],
);
const decrementServings = useCallback(
() => setServingMultiplier((m) => Math.max(m - 1, SERVING_MIN)),
[],
);
/* ── Checked ingredients ── */
const [checkedIngredients, setCheckedIngredients] = useState<Set<string>>(
new Set(),
);
const toggleIngredient = useCallback((localId: string) => {
setCheckedIngredients((prev) => {
const next = new Set(prev);
if (next.has(localId)) next.delete(localId);
else next.add(localId);
return next;
});
}, []);
/* ── Derived data ── */
const youtubeId = useMemo(
() => (recipe?.youtubeLink ? extractYoutubeId(recipe.youtubeLink) : null),
[recipe?.youtubeLink],
);
const isOwner =
!!recipe &&
(session?.user as { id?: string } | undefined)?.id === recipe.createdBy;
const sortedSteps = useMemo(
() => (recipe ? sortByOrder(recipe.preparationSteps) : []),
[recipe],
);
return {
recipe,
loading,
error,
servingMultiplier,
adjustedServings,
checkedIngredients,
toggleIngredient,
incrementServings,
decrementServings,
youtubeId,
isOwner,
sortedSteps,
};
};
|